home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / segar.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  24KB  |  824 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ***************************************************************************/
  8.  
  9. #include "driver.h"
  10. #include "vidhrdw/generic.h"
  11.  
  12.  
  13. unsigned char *segar_characterram;
  14. unsigned char *segar_characterram2;
  15. unsigned char *segar_mem_colortable;
  16. unsigned char *segar_mem_bcolortable;
  17.  
  18. typedef struct
  19. {
  20.     unsigned char dirtychar[256];        // graphics defined in RAM, mark when changed
  21.  
  22.     unsigned char colorRAM[0x40];        // stored in a 93419 (vid board)
  23.     unsigned char bcolorRAM[0x40];        // stored in a 93419 (background board)
  24.     unsigned char color_write_enable;    // write-enable the 93419 (vid board)
  25.     unsigned char flip;                    // cocktail flip mode (vid board)
  26.     unsigned char bflip;                // cocktail flip mode (background board)
  27.  
  28.     unsigned char refresh;                // refresh the screen
  29.     unsigned char brefresh;                // refresh the background
  30.     unsigned char char_refresh;            // refresh the character graphics
  31.  
  32.     unsigned char has_bcolorRAM;        // do we have background color RAM?
  33.     unsigned char background_enable;    // draw the background?
  34.     unsigned int back_scene;
  35.     unsigned int back_charset;
  36.  
  37.     // used for Pig Newton
  38.     unsigned int bcolor_offset;
  39.  
  40.     // used for Space Odyssey
  41.     unsigned char backfill;
  42.     unsigned char fill_background;
  43.     unsigned int backshift;
  44.     struct osd_bitmap *horizbackbitmap;
  45.     struct osd_bitmap *vertbackbitmap;
  46. } SEGAR_VID_STRUCT;
  47.  
  48. static SEGAR_VID_STRUCT sv;
  49.  
  50. /***************************************************************************
  51.  
  52.   The Sega raster games don't have a color PROM.  Instead, it has a color RAM
  53.   that can be filled with bytes of the form BBGGGRRR.  We'll still build up
  54.   an initial palette, and set our colortable to point to a different color
  55.   for each entry in the colortable, which we'll adjust later using
  56.   palette_change_color.
  57.  
  58. ***************************************************************************/
  59.  
  60. void segar_init_colors(unsigned char *palette, unsigned short *colortable, const unsigned char *color_prom)
  61. {
  62.     static unsigned char color_scale[] = {0x00, 0x40, 0x80, 0xC0 };
  63.     int i;
  64.  
  65.     /* Our first color needs to be black (transparent) */
  66.     *(palette++) = 0;
  67.     *(palette++) = 0;
  68.     *(palette++) = 0;
  69.  
  70.     /* Space Odyssey uses a static palette for the background, so
  71.        our choice of colors isn't exactly arbitrary.  S.O. uses a
  72.        6-bit color setup, so we make sure that every 0x40 colors
  73.        gets a nice 6-bit palette.
  74.  
  75.        (All of the other G80 games overwrite the default colors on startup)
  76.     */
  77.     for (i = 0;i < (Machine->drv->total_colors - 1);i++)
  78.     {
  79.         *(palette++) = color_scale[((i & 0x30) >> 4)];
  80.         *(palette++) = color_scale[((i & 0x0C) >> 2)];
  81.         *(palette++) = color_scale[((i & 0x03) << 0)];
  82.     }
  83.  
  84.     for (i = 0;i < Machine->drv->total_colors;i++)
  85.         colortable[i] = i;
  86.  
  87. }
  88.  
  89.  
  90. /***************************************************************************
  91. The two bit planes are separated in memory.  If either bit plane changes,
  92. mark the character as modified.
  93. ***************************************************************************/
  94.  
  95. WRITE_HANDLER( segar_characterram_w )
  96. {
  97.     sv.dirtychar[offset / 8] = 1;
  98.  
  99.     segar_characterram[offset] = data;
  100. }
  101.  
  102. WRITE_HANDLER( segar_characterram2_w )
  103. {
  104.     sv.dirtychar[offset / 8] = 1;
  105.  
  106.     segar_characterram2[offset] = data;
  107. }
  108.  
  109. /***************************************************************************
  110. The video port is not entirely understood.
  111. D0 = FLIP
  112. D1 = Color Write Enable (vid board)
  113. D2 = ??? (we seem to need a char_refresh when this is set)
  114. D3 = ??? (looks to be unused on the schems)
  115. D4-D7 = unused?
  116. ***************************************************************************/
  117.  
  118. WRITE_HANDLER( segar_video_port_w )
  119. {
  120.     logerror("VPort = %02X\n",data);
  121.  
  122.     if ((data & 0x01) != sv.flip)
  123.     {
  124.         sv.flip=data & 0x01;
  125.         sv.refresh=1;
  126.     }
  127.  
  128.     if (data & 0x02)
  129.         sv.color_write_enable=1;
  130.     else
  131.         sv.color_write_enable=0;
  132.  
  133.     if (data & 0x04)
  134.         sv.char_refresh=1;
  135. }
  136.  
  137. /***************************************************************************
  138. If a color changes, refresh the entire screen because it's possible that the
  139. color change affected the transparency (switched either to or from black)
  140. ***************************************************************************/
  141. WRITE_HANDLER( segar_colortable_w )
  142. {
  143.     static unsigned char red[] = {0x00, 0x24, 0x49, 0x6D, 0x92, 0xB6, 0xDB, 0xFF };
  144.     static unsigned char grn[] = {0x00, 0x24, 0x49, 0x6D, 0x92, 0xB6, 0xDB, 0xFF };
  145.     static unsigned char blu[] = {0x00, 0x55, 0xAA, 0xFF };
  146.  
  147.     if (sv.color_write_enable)
  148.     {
  149.         int r,g,b;
  150.  
  151.         b = blu[(data & 0xC0) >> 6];
  152.         g = grn[(data & 0x38) >> 3];
  153.         r = red[(data & 0x07)];
  154.  
  155.         palette_change_color(offset+1,r,g,b);
  156.  
  157.         if (data == 0)
  158.             Machine->gfx[0]->colortable[offset] = Machine->pens[0];
  159.         else
  160.             Machine->gfx[0]->colortable[offset] = Machine->pens[offset+1];
  161.  
  162.         // refresh the screen if the color switched to or from black
  163.         if (sv.colorRAM[offset] != data)
  164.         {
  165.             if ((sv.colorRAM[offset] == 0) || (data == 0))
  166.             {
  167.                 sv.refresh = 1;
  168.             }
  169.         }
  170.  
  171.         sv.colorRAM[offset] = data;
  172.     }
  173.     else
  174.     {
  175.         logerror("color %02X:%02X (write=%d)\n",offset,data,sv.color_write_enable);
  176.         segar_mem_colortable[offset] = data;
  177.     }
  178. }
  179.  
  180. WRITE_HANDLER( segar_bcolortable_w )
  181. {
  182.     static unsigned char red[] = {0x00, 0x24, 0x49, 0x6D, 0x92, 0xB6, 0xDB, 0xFF };
  183.     static unsigned char grn[] = {0x00, 0x24, 0x49, 0x6D, 0x92, 0xB6, 0xDB, 0xFF };
  184.     static unsigned char blu[] = {0x00, 0x55, 0xAA, 0xFF };
  185.  
  186.     int r,g,b;
  187.  
  188.     if (sv.has_bcolorRAM)
  189.     {
  190.         sv.bcolorRAM[offset] = data;
  191.  
  192.         b = blu[(data & 0xC0) >> 6];
  193.         g = grn[(data & 0x38) >> 3];
  194.         r = red[(data & 0x07)];
  195.  
  196.         palette_change_color(offset+0x40+1,r,g,b);
  197.     }
  198.  
  199.     // Needed to pass the self-tests
  200.     segar_mem_bcolortable[offset] = data;
  201. }
  202.  
  203. /***************************************************************************
  204.  
  205.   Draw the game screen in the given osd_bitmap.
  206.   Do NOT call osd_update_display() from this function, it will be called by
  207.   the main emulation engine.
  208.  
  209. ***************************************************************************/
  210.  
  211.  
  212. int segar_vh_start(void)
  213. {
  214.     if (generic_vh_start()!=0)
  215.         return 1;
  216.  
  217.     // Init our vid struct, everything defaults to 0
  218.     memset(&sv, 0, sizeof(SEGAR_VID_STRUCT));
  219.  
  220.     return 0;
  221. }
  222.  
  223. /***************************************************************************
  224. This is the refresh code that is common across all the G80 games.  This
  225. corresponds to the VIDEO I board.
  226. ***************************************************************************/
  227. static void segar_common_screenrefresh(struct osd_bitmap *bitmap, int sprite_transparency, int copy_transparency)
  228. {
  229.     int offs;
  230.     int charcode;
  231.  
  232.     /* for every character in the Video RAM, check if it has been modified */
  233.     /* since last time and update it accordingly. */
  234.     for (offs = videoram_size - 1;offs >= 0;offs--)
  235.     {
  236.         if ((sv.char_refresh) && (sv.dirtychar[videoram[offs]]))
  237.             dirtybuffer[offs]=1;
  238.  
  239.         /* Redraw every character if our palette or scene changed */
  240.         if ((dirtybuffer[offs]) || sv.refresh)
  241.         {
  242.             int sx,sy;
  243.  
  244.             sx = 8 * (offs % 32);
  245.             sy = 8 * (offs / 32);
  246.  
  247.             if (sv.flip)
  248.             {
  249.                 sx = 31*8 - sx;
  250.                 sy = 27*8 - sy;
  251.             }
  252.  
  253.             charcode = videoram[offs];
  254.  
  255.             /* decode modified characters */
  256.             if (sv.dirtychar[charcode] == 1)
  257.             {
  258.                 decodechar(Machine->gfx[0],charcode,segar_characterram,
  259.                         Machine->drv->gfxdecodeinfo[0].gfxlayout);
  260.                 sv.dirtychar[charcode] = 2;
  261.             }
  262.  
  263.             drawgfx(tmpbitmap,Machine->gfx[0],
  264.                     charcode,charcode>>4,
  265.                     sv.flip,sv.flip,sx,sy,
  266.                     &Machine->drv->visible_area,sprite_transparency,0);
  267.  
  268.             dirtybuffer[offs] = 0;
  269.  
  270.         }
  271.     }
  272.  
  273.     for (offs=0;offs<256;offs++)
  274.         if (sv.dirtychar[offs]==2)
  275.             sv.dirtychar[offs]=0;
  276.  
  277.     /* copy the character mapped graphics */
  278.     copybitmap(bitmap,tmpbitmap,0,0,0,0,&Machine->drv->visible_area,copy_transparency,Machine->pens[0]);
  279.  
  280.     sv.char_refresh=0;
  281.     sv.refresh=0;
  282. }
  283.  
  284.  
  285. /***************************************************************************
  286. "Standard" refresh for games without special background boards.
  287. ***************************************************************************/
  288. void segar_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  289. {
  290.     if (palette_recalc() || full_refresh)
  291.         sv.refresh = 1;
  292.  
  293.     segar_common_screenrefresh(bitmap, TRANSPARENCY_NONE, TRANSPARENCY_NONE);
  294. }
  295.  
  296.  
  297. /***************************************************************************
  298.  ---------------------------------------------------------------------------
  299.  Space Odyssey Functions
  300.  ---------------------------------------------------------------------------
  301. ***************************************************************************/
  302.  
  303. /***************************************************************************
  304.  
  305. Create two background bitmaps for Space Odyssey - one for the horizontal
  306. scrolls that's 4 times wider than the screen, and one for the vertical
  307. scrolls that's 4 times taller than the screen.
  308.  
  309. ***************************************************************************/
  310.  
  311. int spaceod_vh_start(void)
  312. {
  313.     if (segar_vh_start()!=0)
  314.         return 1;
  315.  
  316.     if ((sv.horizbackbitmap = osd_create_bitmap(4*Machine->drv->screen_width,Machine->drv->screen_height)) == 0)
  317.     {
  318.         generic_vh_stop();
  319.         return 1;
  320.     }
  321.  
  322.     if ((sv.vertbackbitmap = osd_create_bitmap(Machine->drv->screen_width,4*Machine->drv->screen_height)) == 0)
  323.     {
  324.         osd_free_bitmap(sv.horizbackbitmap);
  325.         generic_vh_stop();
  326.         return 1;
  327.     }
  328.  
  329.     return 0;
  330. }
  331.  
  332. /***************************************************************************
  333.  
  334. Get rid of the Space Odyssey background bitmaps.
  335.  
  336. ***************************************************************************/
  337.  
  338. void spaceod_vh_stop(void)
  339. {
  340.     osd_free_bitmap(sv.horizbackbitmap);
  341.     osd_free_bitmap(sv.vertbackbitmap);
  342.     generic_vh_stop();
  343. }
  344.  
  345. /***************************************************************************
  346. This port controls which background to draw for Space Odyssey.    The temp_scene
  347. and temp_charset are analogous to control lines used to select the background.
  348. If the background changed, refresh the screen.
  349. ***************************************************************************/
  350.  
  351. WRITE_HANDLER( spaceod_back_port_w )
  352. {
  353.     unsigned int temp_scene, temp_charset;
  354.  
  355.     temp_scene   = (data & 0xC0) >> 6;
  356.     temp_charset = (data & 0x04) >> 2;
  357.  
  358.     if (temp_scene != sv.back_scene)
  359.     {
  360.         sv.back_scene=temp_scene;
  361.         sv.brefresh=1;
  362.     }
  363.     if (temp_charset != sv.back_charset)
  364.     {
  365.         sv.back_charset=temp_charset;
  366.         sv.brefresh=1;
  367.     }
  368.  
  369.     /* Our cocktail flip-the-screen bit. */
  370.     if ((data & 0x01) != sv.bflip)
  371.     {
  372.         sv.bflip=data & 0x01;
  373.         sv.brefresh=1;
  374.     }
  375.  
  376.     sv.background_enable=1;
  377.     sv.fill_background=0;
  378. }
  379.  
  380. /***************************************************************************
  381. This port controls the Space Odyssey background scrolling.    Each write to
  382. this port scrolls the background by one bit.  Faster speeds are achieved
  383. by the program writing more often to this port.  Oddly enough, the value
  384. sent to this port also seems to indicate the speed, but the value itself
  385. is never checked.
  386. ***************************************************************************/
  387. WRITE_HANDLER( spaceod_backshift_w )
  388. {
  389.     sv.backshift= (sv.backshift + 1) % 0x400;
  390.     sv.background_enable=1;
  391.     sv.fill_background=0;
  392. }
  393.  
  394. /***************************************************************************
  395. This port resets the Space Odyssey background to the "top".  This is only
  396. really important for the Black Hole level, since the only way the program
  397. can line up the background's Black Hole with knowing when to spin the ship
  398. is to force the background to restart every time you die.
  399. ***************************************************************************/
  400. WRITE_HANDLER( spaceod_backshift_clear_w )
  401. {
  402.     sv.backshift=0;
  403.     sv.background_enable=1;
  404.     sv.fill_background=0;
  405. }
  406.  
  407. /***************************************************************************
  408. Space Odyssey also lets you fill the background with a specific color.
  409. ***************************************************************************/
  410. WRITE_HANDLER( spaceod_backfill_w )
  411. {
  412.     sv.backfill=data + 0x40 + 1;
  413.     sv.fill_background=1;
  414. }
  415.  
  416. /***************************************************************************
  417. ***************************************************************************/
  418. WRITE_HANDLER( spaceod_nobackfill_w )
  419. {
  420.     sv.backfill=0;
  421.     sv.fill_background=0;
  422. }
  423.  
  424.  
  425. /***************************************************************************
  426. Special refresh for Space Odyssey, this code refreshes the static background.
  427. ***************************************************************************/
  428. void spaceod_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  429. {
  430.     int offs;
  431.     int charcode;
  432.     int sprite_transparency;
  433.     int vert_scene;
  434.  
  435.     unsigned char *back_charmap = memory_region(REGION_USER1);
  436.  
  437.     if (palette_recalc() || full_refresh)
  438.         sv.refresh = 1;
  439.  
  440.     // scenes 0,1 are horiz.  scenes 2,3 are vert.
  441.     vert_scene = !(sv.back_scene & 0x02);
  442.  
  443.     sprite_transparency=TRANSPARENCY_PEN;
  444.  
  445.     /* If the background picture changed, draw the new one in temp storage */
  446.     if (sv.brefresh)
  447.     {
  448.         sv.brefresh=0;
  449.  
  450.         for (offs = 0x1000 - 1; offs >= 0; offs--)
  451.         {
  452.             int sx,sy;
  453.  
  454.             /* Use Vertical Back Scene */
  455.             if (vert_scene)
  456.             {
  457.                 sx = 8 * (offs % 32);
  458.                 sy = 8 * (offs / 32);
  459.  
  460.                 if (sv.bflip)
  461.                 {
  462.                    sx = 31*8 - sx;
  463.                    sy = 127*8 - sy;
  464.                 }
  465.             }
  466.             /* Use Horizontal Back Scene */
  467.             else
  468.             {
  469.                 sx = (8 * (offs % 32)) + (256 * (offs >> 10));
  470.                 sy = 8 * ((offs & 0x3FF) / 32);
  471.  
  472.                 if (sv.bflip)
  473.                 {
  474.                    sx = 127*8 - sx;
  475.                    sy = 31*8 - sy; /* is this right? */
  476.                 }
  477.             }
  478.  
  479.  
  480.             charcode = back_charmap[(sv.back_scene*0x1000) + offs];
  481.  
  482.             if (vert_scene)
  483.             {
  484.                 drawgfx(sv.vertbackbitmap,Machine->gfx[1 + sv.back_charset],
  485.                       charcode,0,
  486.                       sv.bflip,sv.bflip,sx,sy,
  487.                       0,TRANSPARENCY_NONE,0);
  488.             }
  489.             else
  490.             {
  491.                 drawgfx(sv.horizbackbitmap,Machine->gfx[1 + sv.back_charset],
  492.                       charcode,0,
  493.                       sv.bflip,sv.bflip,sx,sy,
  494.                       0,TRANSPARENCY_NONE,0);
  495.             }
  496.         }
  497.     }
  498.  
  499.     /* Copy the scrolling background */
  500.     {
  501.         int scrollx,scrolly;
  502.  
  503.         if (vert_scene)
  504.         {
  505.             if (sv.bflip)
  506.                 scrolly = sv.backshift;
  507.             else
  508.                 scrolly = -sv.backshift;
  509.  
  510.             copyscrollbitmap(bitmap,sv.vertbackbitmap,0,0,1,&scrolly,&Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  511.         }
  512.         else
  513.         {
  514.             if (sv.bflip)
  515.                 scrollx = sv.backshift;
  516.             else
  517.                 scrollx = -sv.backshift;
  518.  
  519.             scrolly = -32;
  520.  
  521.             copyscrollbitmap(bitmap,sv.horizbackbitmap,1,&scrollx,1,&scrolly,&Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  522.         }
  523.     }
  524.  
  525.     if (sv.fill_background==1)
  526.     {
  527.         fillbitmap(bitmap,Machine->pens[sv.backfill],&Machine->drv->visible_area);
  528.     }
  529.  
  530.     /* Refresh the "standard" graphics */
  531.     segar_common_screenrefresh(bitmap, TRANSPARENCY_NONE, TRANSPARENCY_PEN);
  532. }
  533.  
  534.  
  535. /***************************************************************************
  536.  ---------------------------------------------------------------------------
  537.  Monster Bash Functions
  538.  ---------------------------------------------------------------------------
  539. ***************************************************************************/
  540.  
  541. int monsterb_vh_start(void)
  542. {
  543.     if (segar_vh_start()!=0)
  544.         return 1;
  545.  
  546.     sv.has_bcolorRAM = 1;
  547.     return 0;
  548. }
  549.  
  550. /***************************************************************************
  551. This port controls which background to draw for Monster Bash.  The tempscene
  552. and tempoffset are analogous to control lines used to bank switch the
  553. background ROMs.  If the background changed, refresh the screen.
  554. ***************************************************************************/
  555.  
  556. WRITE_HANDLER( monsterb_back_port_w )
  557. {
  558.     unsigned int temp_scene, temp_charset;
  559.  
  560.     temp_scene   = 0x400 * ((data & 0x70) >> 4);
  561.     temp_charset = data & 0x03;
  562.  
  563.     if (sv.back_scene != temp_scene)
  564.     {
  565.         sv.back_scene = temp_scene;
  566.         sv.refresh=1;
  567.     }
  568.     if (sv.back_charset != temp_charset)
  569.     {
  570.         sv.back_charset = temp_charset;
  571.         sv.refresh=1;
  572.     }
  573.  
  574.     /* This bit turns the background off and on. */
  575.     if ((data & 0x80) && (sv.background_enable==0))
  576.     {
  577.         sv.background_enable=1;
  578.         sv.refresh=1;
  579.     }
  580.     else if (((data & 0x80)==0) && (sv.background_enable==1))
  581.     {
  582.         sv.background_enable=0;
  583.         sv.refresh=1;
  584.     }
  585. }
  586.  
  587. /***************************************************************************
  588. Special refresh for Monster Bash, this code refreshes the static background.
  589. ***************************************************************************/
  590. void monsterb_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  591. {
  592.     int offs;
  593.     int charcode;
  594.     int sprite_transparency;
  595.  
  596.     unsigned char *back_charmap = memory_region(REGION_USER1);
  597.  
  598.     if (palette_recalc() || full_refresh)
  599.         sv.refresh = 1;
  600.  
  601.     sprite_transparency=TRANSPARENCY_NONE;
  602.  
  603.     /* If the background is turned on, refresh it first. */
  604.     if (sv.background_enable)
  605.     {
  606.         /* for every character in the Video RAM, check if it has been modified */
  607.         /* since last time and update it accordingly. */
  608.         for (offs = videoram_size - 1;offs >= 0;offs--)
  609.         {
  610.             if ((sv.char_refresh) && (sv.dirtychar[videoram[offs]]))
  611.                 dirtybuffer[offs]=1;
  612.  
  613.             /* Redraw every background character if our palette or scene changed */
  614.             if ((dirtybuffer[offs]) || sv.refresh)
  615.             {
  616.                 int sx,sy;
  617.  
  618.                 sx = 8 * (offs % 32);
  619.                 sy = 8 * (offs / 32);
  620.  
  621.                 if (sv.flip)
  622.                 {
  623.                     sx = 31*8 - sx;
  624.                     sy = 27*8 - sy;
  625.                 }
  626.  
  627.                 charcode = back_charmap[offs + sv.back_scene];
  628.  
  629.                 drawgfx(tmpbitmap,Machine->gfx[1 + sv.back_charset],
  630.                     charcode,((charcode & 0xF0)>>4),
  631.                     sv.flip,sv.flip,sx,sy,
  632.                     &Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  633.             }
  634.         }
  635.         sprite_transparency=TRANSPARENCY_PEN;
  636.     }
  637.  
  638.     /* Refresh the "standard" graphics */
  639.     segar_common_screenrefresh(bitmap, sprite_transparency, TRANSPARENCY_NONE);
  640. }
  641.  
  642. /***************************************************************************
  643.  ---------------------------------------------------------------------------
  644.  Pig Newton Functions
  645.  ---------------------------------------------------------------------------
  646. ***************************************************************************/
  647.  
  648. /***************************************************************************
  649. This port seems to control the background colors for Pig Newton.
  650. ***************************************************************************/
  651.  
  652. WRITE_HANDLER( pignewt_back_color_w )
  653. {
  654.     if (offset == 0)
  655.     {
  656.         sv.bcolor_offset = data;
  657.     }
  658.     else
  659.     {
  660.         segar_bcolortable_w(sv.bcolor_offset,data);
  661.     }
  662. }
  663.  
  664. /***************************************************************************
  665. These ports control which background to draw for Pig Newton.  They might
  666. also control other video aspects, since without schematics the usage of
  667. many of the data lines is indeterminate.  Segar_back_scene and segar_backoffset
  668. are analogous to registers used to control bank-switching of the background
  669. "videorom" ROMs and the background graphics ROMs, respectively.
  670. If the background changed, refresh the screen.
  671. ***************************************************************************/
  672.  
  673. WRITE_HANDLER( pignewt_back_ports_w )
  674. {
  675.     unsigned int tempscene;
  676.  
  677.     logerror("Port %02X:%02X\n",offset + 0xb8,data);
  678.  
  679.     /* These are all guesses.  There are some bits still being ignored! */
  680.     switch (offset)
  681.     {
  682.         case 1:
  683.             /* Bit D7 turns the background off and on? */
  684.             if ((data & 0x80) && (sv.background_enable==0))
  685.             {
  686.                 sv.background_enable=1;
  687.                 sv.refresh=1;
  688.             }
  689.             else if (((data & 0x80)==0) && (sv.background_enable==1))
  690.             {
  691.                 sv.background_enable=0;
  692.                 sv.refresh=1;
  693.             }
  694.             /* Bits D0-D1 help select the background? */
  695.             tempscene = (sv.back_scene & 0x0C) | (data & 0x03);
  696.             if (sv.back_scene != tempscene)
  697.             {
  698.                 sv.back_scene = tempscene;
  699.                 sv.refresh=1;
  700.             }
  701.             break;
  702.         case 3:
  703.             /* Bits D0-D1 help select the background? */
  704.             tempscene = ((data << 2) & 0x0C) | (sv.back_scene & 0x03);
  705.             if (sv.back_scene != tempscene)
  706.             {
  707.                 sv.back_scene = tempscene;
  708.                 sv.refresh=1;
  709.             }
  710.             break;
  711.         case 4:
  712.             if (sv.back_charset != (data & 0x03))
  713.             {
  714.                 sv.back_charset = data & 0x03;
  715.                 sv.refresh=1;
  716.             }
  717.             break;
  718.     }
  719. }
  720.  
  721. /***************************************************************************
  722.  ---------------------------------------------------------------------------
  723.  Sinbad Mystery Functions
  724.  ---------------------------------------------------------------------------
  725. ***************************************************************************/
  726.  
  727. /***************************************************************************
  728. Controls the background image
  729. ***************************************************************************/
  730.  
  731. WRITE_HANDLER( sindbadm_back_port_w )
  732. {
  733.     unsigned int tempscene;
  734.  
  735.     /* Bit D7 turns the background off and on? */
  736.     if ((data & 0x80) && (sv.background_enable==0))
  737.     {
  738.         sv.background_enable=1;
  739.         sv.refresh=1;
  740.     }
  741.     else if (((data & 0x80)==0) && (sv.background_enable==1))
  742.     {
  743.         sv.background_enable=0;
  744.         sv.refresh=1;
  745.     }
  746.     /* Bits D2-D6 select the background? */
  747.     tempscene = (data >> 2) & 0x1F;
  748.     if (sv.back_scene != tempscene)
  749.     {
  750.         sv.back_scene = tempscene;
  751.         sv.refresh=1;
  752.     }
  753.     /* Bits D0-D1 select the background char set? */
  754.     if (sv.back_charset != (data & 0x03))
  755.     {
  756.         sv.back_charset = data & 0x03;
  757.         sv.refresh=1;
  758.     }
  759. }
  760.  
  761. /***************************************************************************
  762. Special refresh for Sinbad Mystery, this code refreshes the static background.
  763. ***************************************************************************/
  764. void sindbadm_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  765. {
  766.     int offs;
  767.     int charcode;
  768.     int sprite_transparency;
  769.     unsigned long backoffs;
  770.     unsigned long back_scene;
  771.  
  772.     unsigned char *back_charmap = memory_region(REGION_USER1);
  773.  
  774.     if (palette_recalc() || full_refresh)
  775.         sv.refresh = 1;
  776.  
  777.     sprite_transparency=TRANSPARENCY_NONE;
  778.  
  779.     /* If the background is turned on, refresh it first. */
  780.     if (sv.background_enable)
  781.     {
  782.         /* for every character in the Video RAM, check if it has been modified */
  783.         /* since last time and update it accordingly. */
  784.         for (offs = videoram_size - 1;offs >= 0;offs--)
  785.         {
  786.             if ((sv.char_refresh) && (sv.dirtychar[videoram[offs]]))
  787.                 dirtybuffer[offs]=1;
  788.  
  789.             /* Redraw every background character if our palette or scene changed */
  790.             if ((dirtybuffer[offs]) || sv.refresh)
  791.             {
  792.                 int sx,sy;
  793.  
  794.                 sx = 8 * (offs % 32);
  795.                 sy = 8 * (offs / 32);
  796.  
  797.                 if (sv.flip)
  798.                 {
  799.                     sx = 31*8 - sx;
  800.                     sy = 27*8 - sy;
  801.                 }
  802.  
  803.                 // NOTE: Pig Newton has 16 backgrounds, Sinbad Mystery has 32
  804.                 back_scene = (sv.back_scene & 0x1C) << 10;
  805.  
  806.                 backoffs = (offs & 0x01F) + ((offs & 0x3E0) << 2) + ((sv.back_scene & 0x03) << 5);
  807.  
  808.                 charcode = back_charmap[backoffs + back_scene];
  809.  
  810.                 drawgfx(tmpbitmap,Machine->gfx[1 + sv.back_charset],
  811.                     charcode,((charcode & 0xF0)>>4),
  812.                     sv.flip,sv.flip,sx,sy,
  813.                     &Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  814.             }
  815.         }
  816.         sprite_transparency=TRANSPARENCY_PEN;
  817.     }
  818.  
  819.     /* Refresh the "standard" graphics */
  820.     segar_common_screenrefresh(bitmap, sprite_transparency, TRANSPARENCY_NONE);
  821.  
  822. }
  823.  
  824.